

#ifndef __WRK_LOGGER__H_
#define __WRK_LOGGER__H_

#include <time.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fstream>
#include <execinfo.h>

inline char * NOW()
{
	time_t tt = time(NULL); 
	static char time_buf[30];		
	tm* t= localtime(&tt);	
	sprintf(time_buf,"%d-%02d-%02d %02d:%02d:%02d", 
	t->tm_year + 1900,	
	t->tm_mon + 1,	
	t->tm_mday,		
	t->tm_hour,		
	t->tm_min,		
  	t->tm_sec);	

	return time_buf;
}

inline char *today()
{
	time_t tt = time(NULL); 
	static char time_buf[30];		
	tm* t= localtime(&tt);	
	sprintf(time_buf,"%d%02d%02d", 
	t->tm_year + 1900,	
	t->tm_mon + 1,	
	t->tm_mday);	

	return time_buf;
}

inline void  print_trace()  							
{												
    int size = 0;									
    void *array[20];								
    char **strings = NULL;							
    int i = 0;										
													
    size = backtrace(array, 20);					
    strings = backtrace_symbols(array, size);		
    if (strings == NULL)							
    {												
        perror("backtrace_symbols");				
        exit(-1);									
    }												
													
    printf("Obtained %zd stack frames.\n", size);	
													
    for (i = 0; i < size; i++)						
    {												
        printf("PID:%d  %s\n", getpid(), strings[i]);					
    }												
													
    free(strings);									
    strings = NULL;									
}

// #define CDEBUG std::cout<<NOW()<<" FILE:"<<__FILE__<<"|FUNC:"<<__FUNCTION__<<"|LINE:"<<__LINE__<<"|PID:"<<getpid()<< std::endl

#define CDEBUG std::cout<<"["<<NOW()<<"][console][PID:"<<getpid()<<"]["<<__FUNCTION__<<"@"<<__FILE__<<":"<<__LINE__<<"] "

namespace wrk {
    typedef enum {
        ERROR,
        WARNING,
        INFO,
        DEBUG
    }wrk_log_level_t;

    class WrkLogger
    {
    private:
        /* data */

        static WrkLogger *logger;

        static wrk_log_level_t LOG_LEVEL;

        static std::string log_file;

        static std::string ori_log_file;

        static pthread_mutex_t log_mutex;

        static pthread_mutex_t buffer_mutex;

        static std::string log_backtrace();

    public:
        WrkLogger();
        ~WrkLogger();
        static void init_logger(const std::string &logfile);

        static void log_message(wrk_log_level_t cur_level, const char *file, const char *func, uint32_t line, const std::string  &msg);

        static WrkLogger* get_instance();

        static std::string get_uuid();

        void set_log_level(wrk_log_level_t level);

        static std::string format(const char *fmt, ...);

        void test(std::string msg, const char *file=__FILE__, const char *func=__FUNCTION__, uint32_t line=__LINE__);
    };
}

#define LOG_DEBUG(...) \
do{ \
    std::string msg = server::logger->format(__VA_ARGS__); \
    server::logger->log_message(wrk::wrk_log_level_t::DEBUG, __FILE__, __FUNCTION__, __LINE__, msg); \
}while(0)


#define LOG_INFO(...) \
do{ \
    std::string msg = server::logger->format(__VA_ARGS__); \
    server::logger->log_message(wrk::wrk_log_level_t::INFO, __FILE__, __FUNCTION__, __LINE__, msg); \
}while(0)

#define LOG_WARNING(...) \
do{ \
    std::string msg = server::logger->format(__VA_ARGS__); \
    server::logger->log_message(wrk::wrk_log_level_t::WARNING, __FILE__, __FUNCTION__, __LINE__, msg); \
}while(0)

#define LOG_ERROR(...) \
do{ \
    std::string msg = server::logger->format(__VA_ARGS__); \
    server::logger->log_message(wrk::wrk_log_level_t::ERROR, __FILE__, __FUNCTION__, __LINE__, msg); \
}while(0)



#endif